<?php
// lib/RedisPool.php

namespace Tyrone\Lib;

use Swoole\Coroutine\Channel;
use Swoole\Coroutine\Redis;

class RedisPool
{
    private $pool;
    private $config;
    private $timeout;

    public function __construct(array $config, $size = 10, $timeout = 3.0)
    {
        $this->config = $config;
        $this->timeout = $timeout;
        $this->pool = new Channel($size);

        // 预创建连接
        for ($i = 0; $i < $size; $i++) {
            $redis = $this->createConnection();
            if ($redis) {
                $this->put($redis);
            }
        }
    }

    private function createConnection()
    {
        $redis = new \Redis();

        $host = $this->config['host'] ?? '127.0.0.1';
        $port = $this->config['port'] ?? 6379;
        $ssl = $this->config['ssl'] ?? false;
        $auth = $this->config['auth'] ?? null;

        // 连接 Redis
        $connected = $redis->connect($host, $port, $this->timeout);
        if (!$connected) {
            echo "RedisPool: Failed to connect to {$host}:{$port}\n";
            return null;
        }

        // SSL
        if ($ssl) {
            $redis->ssl = true;
        }

        // 认证
        if ($auth !== null) {
            if (!$redis->auth($auth)) {
                echo "RedisPool: Auth failed\n";
                $redis->close();
                return null;
            }
        }

        // 选择数据库
        $dbIndex = $this->config['database'] ?? 0;
        if ($dbIndex > 0) {
            if (!$redis->select($dbIndex)) {
                echo "RedisPool: Failed to select DB {$dbIndex}\n";
                $redis->close();
                return null;
            }
        }

        return $redis;
    }

    /**
     * 获取一个 Redis 连接（带超时）
     */
    public function get($timeout = 5.0)
    {
        $redis = $this->pool->pop($timeout);
        if ($redis === false) {
            echo "RedisPool: Get connection timeout\n";
            return null;
        }

        // 可选：心跳检测（简单 ping）
        if (!$redis->ping()) {
            echo "RedisPool: Connection dead, reconnecting...\n";
            $redis->close();
            $redis = $this->createConnection();
        }

        return $redis;
    }

    /**
     * 归还连接
     */
    public function put($redis)
    {
        if ($this->pool->isFull()) {
            echo "RedisPool: Pool is full, closing connection.\n";
            $redis->close();
            return false;
        }

        $this->pool->push($redis);
        return true;
    }

    /**
     * 关闭所有连接
     */
    public function close()
    {
        while (!$this->pool->isEmpty()) {
            $redis = $this->pool->pop(0.01);
            if ($redis && $redis instanceof Redis) {
                $redis->close();
            }
        }
    }

    /**
     * 获取当前池中连接数
     */
    public function size()
    {
        return $this->pool->length();
    }

    /**
     * 获取空闲连接数
     */
    public function idle()
    {
        return $this->pool->length();
    }
}